<!--
 * @Author: yangzhiyu yangzhiyu@mail.pigcms.com
 * @Date: 2024-03-29 16:56:47
 * @LastEditors: yangzhiyu yangzhiyu@mail.pigcms.com
 * @LastEditTime: 2024-04-01 16:27:39
 * @FilePath: \fe_user_pc\src\views\shotstack\MuseMixedCut\MixedCutPreview\components\saveVideoDialog.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
   音色选择
-->
<script setup>
import baseModel from "@/components/baseModel/baseModel.vue";
import { computed, onMounted, reactive, ref, nextTick, watch } from "vue";
import request from "@/common/utils/request";
import storeAi from "@/store/index";

// icon
import {
  CaretRightOutlined,
  PauseOutlined,
  RedoOutlined,
} from "@ant-design/icons-vue";
import { message } from "ant-design-vue";

// 仓库
import { useStore } from "vuex";

const appName = ref()

const store = useStore();
// 收集数据
let state = reactive({
  name: "", // 音色名称
  human_style: "", // 音色介绍
  img: "", // 音色头像
  voice_type: "", // 音色id
  volume: 1, // 音量
  speed: 1, // 语速
  emotion_category: "", // 情感类型
  emotion_intensity: 50, // 情感程度
});
const emit = defineEmits(["closeAudioSelection"]);
// 预期列表
const toneList = ref([]);
// 场景和音色列表
const voiceData = reactive({
  category: [],
  list: [],
});

onMounted(() => {
  getVoiceData();
  storeAi.dispatch("getAiConfig").then((aiConfig) => {
    appName.value = aiConfig.site_name
  })
});

// 获取场景数据
const getVoiceData = async () => {
  const res = await request.get("/work_ai", "/user/shotstack/voice/category");
  voiceData.category = res.result;



  console.log(res, "场景列表");
  getVoiceList();
};

// 获取音色列表
const getVoiceList = async () => {
  const res = await request.get("/work_ai", "/user/shotstack/voice/list", {
    category: activeKey.value,
  });
  if (res.result.length > 0) {
    voiceData.list = res.result;
    toneList.value = voiceData.list[0].item[0].emotion_style;
    console.log(voiceData.list, "音色列表");
    toneList.value.length == 1 &&
      (state.emotion_category = toneList.value[0].key);
  }
};

// 音频播放器
const audioRef = ref(null);
const voiceUrl = ref(null);
// 播放声音
const playFlage = ref(true); // false , 显示试听
const playitem = ref(null); // 存放当期那预览声音的id
const loding = ref(false);
const playVoice = (item) => {
  // playFlage.value = !playFlage.value
  // 相同 , 并且正在播放, 暂停
  if (playitem.value == item.id) {
    playFlage.value ? audioRef.value.pause() : audioRef.value.play();
    // playFlage.value = false
    playFlage.value = !playFlage.value;
  } else {
    // 不同或首次播放
    playitem.value = item.id;
    playFlage.value = true;
    loding.value = true;
    voiceUrl.value = item.voice_url;
    console.log(voiceUrl.value);
    nextTick(() => {
      audioRef.value.play();
      loding.value = false;
    });
  }
};

// 判断是否显示正在播放状态
const playState = (id) => {
  if (playitem.value !== id) return false;
  if (playFlage.value) {
    return true;
  } else {
    return false;
  }
};

// 播放结束
const handleAudioEnded = () => {
  playFlage.value = false;
  audioRef.value.currentTime = 0;
};

// 全局音色试听
const globalAudio = ref(null);
const globalPlay = ref(false); // false - 暂停 显示播放
const globalAudioUrl = ref("");
const handleGlobalAudioEnded = () => {
  globalAudio.value.currentTime = 0;
  globalPlay.value = false;
  console.log("调用了", globalPlay.value);
};

/**
 * 文案试听
 */

// 当前选择的项
const selectVoice = computed(() => {
  return (
    voiceData.list
      .flatMap((ele) => ele.item)
      .find((i) => i.timbre_id == state.voice_type) || null
  );
});
const audition = ref(`欢迎使用${appName.value}视频文字转语音工具`);

//  按钮是否加载中
const btnLoding = ref(false);
const paramsData = computed(() => {
  return {
    text: audition.value,
    speed: state.speed,
    timbre_id: selectVoice.value?.timbre_id || null,
    volume: state.volume,
    emotion_category: state.emotion_category,
    emotion_intensity: state.emotion_intensity,
  };
});
const isChange = ref(false);
watch(
  () => paramsData.value,
  (nv, ov) => {
    isChange.value = true;
  },
  {
    deep: true,
  }
);

// 点击播放按钮
const auditionPlay = () => {
  if (!audition.value.trim()) return message.warn("请输入文案");
  if (!selectVoice.value) return message.warn("请选择想要试听的音色");
  if (!isChange.value && globalAudioUrl.value && globalPlay.value) {
    // 数据无变化, 有url 播放中 => 暂停
    globalAudio.value.pause();
    globalPlay.value = false;
    return;
  } else if (!isChange.value && globalAudioUrl.value && !globalPlay.value) {
    // 数据无变化 , 有url 暂停中 => 播放
    globalAudio.value.play();
    globalPlay.value = true;
    return;
  }
  btnLoding.value = true;
  request
    .get("/work_ai", "/user/shotstack/textToVoice", paramsData.value)
    .then((res) => {
      let tiem = setInterval(() => {
        request
          .get("/work_ai", "/user/shotstack/getVoice", {
            task_id: res.result.task_id,
            request_id: res.result.request_id || ''
          })
          .then((task) => {
            if (task.result.Data.ResultUrl) {
              console.log(task, "获取的音频");
              clearInterval(tiem);
              voiceUrl.value = task.result.Data.ResultUrl;
              btnLoding.value = false;
              globalAudioUrl.value = task.result.Data.ResultUrl;
              isChange.value = false;
              nextTick(() => {
                globalAudio.value && globalAudio.value.play();
                globalPlay.value = true;
              });
            }
          });
      }, 1000);
    });
};

// 判断右侧音量重置按钮 是否展示
const resetShow = computed(() => {
  return state.emotion_intensity == 1 && state.speed == 1 && state.volume == 1;
});

const tabsChange = (activeKey) => {
  getVoiceList();
};

const dialog = ref(null);

// 选择某项卡片
const selectCart = (item) => {
  console.log(item, "选中的某项");
  state.voice_type = item.timbre_id;
  state.name = item.name;
  state.img = item.img;
  state.human_style = item.human_style;
};
// 打开弹窗
const showModal = (info) => {
  state = reactive(JSON.parse(JSON.stringify(info))); // 将 state 更改为响应式对象
  dialog.value.showModal();
};
// 关闭弹窗
const closeModal = () => {
  dialog.value.closeModal();
};

// 数据保存
const upgradePackage = () => {
  // 通知父组件更新数据
  emit("closeAudioSelection", state);
  closeModal(); //关闭弹窗
};
// 取消
const cancel = () => {
  closeModal();
};

// 当前tabs 选择的项
const activeKey = ref("common");

defineExpose({
  showModal,
  closeModal,
});
</script>

<template>
  <div class="AudioSelection">
    <baseModel
      ref="dialog"
      :contentWidth="'1154px'"
      minWidth="1154px"
      :zIndex="9999"
      :getContainer="() => document.queryselector('.AudioSelection')"
    >
      <!-- minWidth='1140px' -->

      <template #title>
        <div class="title_box">
          <span>声音</span>
        </div>
      </template>
      <template #content>
        <div class="content">
          <div class="tabs">
            <a-tabs v-model:activeKey="activeKey" @change="tabsChange">
              <a-tab-pane
                v-for="i in voiceData.category"
                :key="i.key"
                :tab="i.value"
              >
                <!-- 声音 卡片 -->
                <div class="voice_cart_content" v-for="(v1, index) in voiceData.list" :key="index">
                  <div class="voice">
                    <span class="voice_cart_title">{{ v1.gender_title }}</span>
                    <div class="voice_cart_list">
                      <div v-for="(v2, index2) in voiceData.list[index]?.item" :key="index2"
                        class="voice_cart"
                        :class="{
                          active_voice_cart: v2.timbre_id == state.voice_type,
                        }"
                        @click="selectCart(v2)" >
                        <div class="voice_left">
                          <div class="imgBox">
                            <img :src="v2.img" alt="" />
                            <div
                              class="play_or_stop"
                              @click.stop="playVoice(v2)"
                            >
                              <PauseOutlined v-if="playState(v2.id)" />
                              <CaretRightOutlined v-else />
                            </div>
                          </div>
                          <div class="described">
                            <span>{{ v2.name }}</span>
                            <span>{{ v2.human_style }}</span>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>

                  <!-- <div
                    class="voice"
                    v-if="voiceData.list[1] && voiceData.list[1]?.item.length"
                  >
                    <span class="voice_cart_title">男声</span>
                    <div class="voice_cart_list">
                      <div
                        class="voice_cart"
                        :class="{
                          active_voice_cart: i.timbre_id == state.voice_type,
                        }"
                        @click="selectCart(i)"
                        v-for="i in voiceData.list[1]?.item"
                        :key="i"
                      >
                        <div class="voice_left">
                          <div class="imgBox">
                            <img :src="i.img" alt="" />
                            <div
                              class="play_or_stop"
                              @click.stop="playVoice(i)"
                            >
                              <PauseOutlined v-if="playState(i.id)" />
                              <CaretRightOutlined v-else />
                            </div>
                          </div>
                          <div class="described">
                            <span>{{ i.name }}</span>
                            <span>{{ i.human_style }}</span>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div> -->
                </div>
              </a-tab-pane>
            </a-tabs>
          </div>
          <!-- 声音配置 -->
          <div class="voice_config">
            <!-- 重置按钮 -->
            <span
              :style="{ opacity: resetShow ? 0 : 1 }"
              class="reset_btn"
              @click="resetState"
            >
              <RedoOutlined />
            </span>

            <div class="config_cart">
              <span>音量 {{ state.volume }}</span>
              <div class="slider_box">
                <span>1</span>
                <a-slider
                  class="slider"
                  :min="1"
                  :max="11"
                  id="test"
                  :step="1"
                  v-model:value="state.volume"
                />
                <span>11</span>
              </div>
            </div>
            <div class="config_cart">
              <span>语速 {{ state.speed }}</span>
              <div class="slider_box">
                <span>-2×</span>
                <a-slider
                  class="slider"
                  :min="-2"
                  :max="2"
                  id="test"
                  :step="1"
                  v-model:value="state.speed"
                />
                <span>2×</span>
              </div>
            </div>
            <div class="config_cart">
              <span>情感 {{ state.emotion_intensity }}</span>
              <div class="slider_box">
                <span>50</span>
                <a-slider
                  class="slider"
                  :min="50"
                  :max="200"
                  id="test"
                  :step="1"
                  v-model:value="state.emotion_intensity"
                />
                <span>200</span>
              </div>
            </div>
            <div class="config_cart">
              <span style="margin-right: 10px">语气 </span>
              <a-select
                :disabled="toneList.length == 1"
                size="small"
                style="width: 160px; margin-right: 30px"
                :getPopupContainer="
                  (triggerNode) => {
                    return triggerNode.closest('.voice_config');
                  }
                "
                ref="select"
                v-model:value="state.emotion_category"
              >
                <a-select-option
                  v-for="item in toneList"
                  :value="item.key"
                  :key="item.key"
                >
                  {{ item.value }}
                </a-select-option>
              </a-select>
            </div>
            <!-- 文案试听 -->
            <!-- <div class="audition_box">
              <a-textarea
                :bordered="false"
                v-model:value="audition"
                :autoSize="{ minRows: 6 }"
                :maxlength="500"
                show-count
              >
              </a-textarea>

              <a-button
                :loading="btnLoding"
                @click="auditionPlay"
                type="primary"
                style="height: 28px; font-size: 13px"
                class="audition_btn"
              >
                {{ globalPlay ? "暂停" : "播放" }}
              </a-button>
            </div> -->
          </div>
        </div>
      </template>
      <template #footer>
        <div class="bottom">
          <a-button
            class="btn"
            key="back"
            @click="cancel"
            style="margin-right: 10px"
            >取消</a-button
          >
          <a-button
            class="btn"
            key="submit"
            type="primary"
            :loading="loading"
            :disabled="disableSubmit"
            @click="upgradePackage"
            >保存</a-button
          >
        </div>
      </template>
    </baseModel>

    <!-- 每个音频的试听audio节点 -->
    <audio
      @ended="handleAudioEnded"
      ref="audioRef"
      :src="voiceUrl"
      style="display: none"
    ></audio>
    <!-- 预览自定义音色的音频节点 -->
    <audio
      @ended="handleGlobalAudioEnded"
      ref="globalAudio"
      :src="globalAudioUrl"
      style="display: none"
    ></audio>
  </div>
</template>

<style lang="less" scoped>
.AudioSelection {
  height: 100%;
}
.title_box {
  span {
    font-size: 18px;
    color: #0c0d0e;
  }
}
.content {
  display: flex;

  .tabs {
    flex: 1;
    .voice_cart_content {
      // height: 100%;
      max-height: 550px;
      overflow-y: auto;
      &:hover {
        &::-webkit-scrollbar {
          display: block;
        }
        // padding-right: 0;
      }
      &::-webkit-scrollbar {
        width: 10px;
        /* 滚动条的宽度 */
        height: 10px;
        /* 滚动条的高度，垂直滚动条可能用得上 */
        display: none;
      }

      &::-webkit-scrollbar-thumb {
        background: #888;
        /* 滑块的背景颜色 */
        border-radius: 10px;
        /* 滑块的圆角 */
      }
      .voice {
        display: flex;
        flex-direction: column;
        .voice_cart_title {
          margin-bottom: 10px;
          font-size: 15px;
          font-weight: 600;
        }
        .voice_cart_list {
          display: flex;
          flex-wrap: wrap;
          .voice_cart {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px 16px;
            width: 200px;
            min-height: 80px;
            border: 1px solid #e5e5e5;
            border-radius: 8px;
            cursor: pointer;
            margin-bottom: 15px;
            margin-right: 25px;
            &:hover {
              background-color: #f9f9f9;
              .play_or_stop {
                opacity: 1 !important;
              }
            }
            .voice_left {
              display: flex;
              align-items: center;
              .described {
                display: flex;
                flex-direction: column;
              }
              .imgBox {
                position: relative;
                border-radius: 30px;
                overflow: hidden;
                margin-right: 20px;
                img {
                  width: 32px;
                }

                .play_or_stop {
                  position: absolute;
                  left: 0;
                  top: 0;
                  z-index: 1;
                  height: 100%;
                  width: 100%;
                  background-color: #b6b6b685;
                  text-align: center;
                  line-height: 32px;
                  font-size: 18px;
                  opacity: 0;
                  transition: opacity 0.3s;
                }
              }
            }
          }
          .active_voice_cart {
            border-color: #1664ff !important;
            background-color: #e8f4ff !important;
          }
        }
      }
    }
  }

  // 音色配置
  .voice_config {
    width: 330px;
    margin-top: 45px;
    border-top: 1px solid #f0f0f0;
    padding: 0 34px 0 55px;
    position: relative;

    // 文案试听
    .audition_box {
      border: 1px solid #e5e5e5;
      padding: 10px;
      padding-bottom: 40px;

      // padding-left: 20px;
      position: relative;
      .audition_btn {
        position: absolute;
        left: 21px;
        bottom: 10px;
      }
    }

    .reset_btn {
      position: absolute;
      top: 30px;
      right: 34px;
      transition: opacity 0.3s;
      cursor: pointer;
      font-size: 16px;
    }
    .config_cart {
      margin-top: 32px;
      .slider_box {
        display: flex;
        align-items: center;
        span {
          font-size: 12px;
          color: #727477;
        }
        .slider {
          flex: 1;
        }
      }
    }
    .audition_box {
      margin-top: 32px;
    }
  }
}

.bottom {
  // display: flex;
  // justify-content: center;
  // align-items: center;

  // .btn {
  //     border-radius: 4px;
  //     overflow: hidden;
  // }
}
</style>
